package com.realgodo.site.service.relation;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.orm.Page;
import org.springside.modules.orm.hibernate.DefaultEntityManager;

import com.realgodo.site.entity.relation.Friend;
import com.realgodo.site.entity.relation.Relation;
import com.realgodo.site.entity.space.Space;

@Service
@Transactional
public class FriendManager extends DefaultEntityManager<Friend, Long> {

	@Autowired
	protected SessionFactory sessionFactory;

	/**
	 * 拆旬用户朋友实体集合
	 * 
	 * @param spaceId
	 *            空间id
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<Friend> getFriendList(Long spaceId) {
		Criteria c = sessionFactory.getCurrentSession().createCriteria(
				Friend.class);
		this.addFriendRestrictions(c, spaceId);
		c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
		return c.list();
	}

	/**
	 * 查询用户朋友实体集合
	 * 
	 * @param spaceId
	 *            空间id
	 * @return
	 */
	public Page<Friend> find(int pageSize, Map<String, Object> param) {
		Page<Friend> page = new Page<Friend>(pageSize);
		Criteria c = sessionFactory.getCurrentSession().createCriteria(
				Friend.class);
		if (param == null) {
			page.setPageNo(1);
			return this.entityDao.findByCriteria(page, c);
		}

		page.setPageNo(super.isParamNotNull(param, Page.PAGE) ? Integer
				.valueOf((String) getParamValue(param, Page.PAGE)) : 1);// 查询页数
		if (isParamNotNull(param, "receiverId")) {
			c.add(Restrictions.eq("receiver.id", Long
					.valueOf((String) getParamValue(param, "receiverId"))));
		} else if (isParamNotNull(param, "spaceId")) {
			c.add(Restrictions
					.or(
							Restrictions.eq("sender.id", Long
									.valueOf((String) getParamValue(param,
											"spaceId"))), Restrictions.eq(
									"receiver.id", Long
											.valueOf((String) getParamValue(
													param, "spaceId")))));
		}
		if (isParamNotNull(param, "status")) {
			c.add(Restrictions.eq("status", Integer
					.valueOf((String) getParamValue(param, "status"))));
		}
		c.addOrder(Order.desc("id"));
		return entityDao.findByCriteria(page, c);
	}

	/**
	 * 获取等待审核的朋友数量
	 * 
	 * @param mySpace
	 * @return
	 */
	public Long getNewFriendCount(Space mySpace) {
		Session session = this.sessionFactory.getCurrentSession();
		String hql = "select count(o) from Friend o where o.status = "
				+ Relation.STATUS_NEW + " and o.receiver.id = "
				+ mySpace.getId();
		Query q = session.createQuery(hql);
		return (Long) q.uniqueResult();
	}

	/**
	 * 拆旬用户朋友SpaceId集合
	 * 
	 * @param spaceId
	 *            空间id
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<Long> getFriendSpaceIdList(Long spaceId) {
		Criteria c = sessionFactory.getCurrentSession().createCriteria(
				Friend.class);
		ProjectionList projectionList = Projections.projectionList();// 映射条件
		projectionList.add(Projections.property("sender.id").as("sender_id"));// 发出者id
		projectionList.add(Projections.property("receiver.id")
				.as("receiver_id"));// 发出者id
		c.setProjection(projectionList);
		this.addFriendRestrictions(c, spaceId);
		List<Object[]> ids = c.list();
		if (ids == null || ids.size() == 0) {
			return new ArrayList<Long>();
		}
		Set<Long> set = new HashSet<Long>();
		for (Object[] o : ids) {
			for (Object sid : o) {
				set.add((Long) sid);
			}
		}
		return new ArrayList<Long>(set);
	}

	/**
	 * 判断是否是朋友 1:是朋友 0:交友申请待审核 -1 未申请 或 交友申请被拒绝
	 * */
	@SuppressWarnings("unchecked")
	public int isFriend(Long ownerId, Long targetId) {
		Criteria c = sessionFactory.getCurrentSession().createCriteria(
				Friend.class);
		c.add(Restrictions.or(Restrictions.and(Restrictions.eq("sender.id",
				ownerId), Restrictions.eq("receiver.id", targetId)),
				Restrictions.and(Restrictions.eq("receiver.id", ownerId),
						Restrictions.eq("sender.id", targetId))));
		c.addOrder(Order.desc("id"));
		List<Friend> friends = c.list();
		if (friends == null || friends.size() == 0) {
			return Friend.STATUS_REJECT;
		}
		Friend f = friends.get(0);
		return f.getStatus();
	}

	private void addFriendRestrictions(Criteria c, Long spaceId) {
		c.add(Restrictions.or(Restrictions.eq("sender.id", spaceId),
				Restrictions.eq("receiver.id", spaceId)));
		c.add(Restrictions.eq("status", Relation.STATUS_AGREE));
		c.addOrder(Order.desc("id"));

		// c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
	}

}
